﻿using System;
using System.Web.Security;
using System.Security.Principal;
using System.Runtime.InteropServices;

namespace PreContractWeb
{
	public class ImpersonationException: Exception
	{
		public ImpersonationException():base()
		{
		}

		public ImpersonationException(string message):base(message)
		{
		}

		public ImpersonationException(string message, Exception innerException):base(message, innerException)
		{
		}
	}

	/// <summary>
	/// ImpersonateHelper 的摘要说明。
	/// </summary>
	public class ImpersonateHelper
	{
		public ImpersonateHelper()
		{
			//
			// TODO: 在此处添加构造函数逻辑
			//
		}

		public const int LOGON32_LOGON_INTERACTIVE = 2;
		public const int LOGON32_PROVIDER_DEFAULT = 0;

		WindowsImpersonationContext impersonationContext; 

		[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
		public static extern int LogonUser(String lpszUserName, 
			String lpszDomain,
			String lpszPassword,
			int dwLogonType, 
			int dwLogonProvider,
			ref IntPtr phToken);
		
		[DllImport("advapi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto, SetLastError=true)]
		public extern static int DuplicateToken(IntPtr hToken, 
			int impersonationLevel,  
			ref IntPtr hNewToken);

        [DllImport("advapi32.dll", CharSet=CharSet.Auto)]
		public extern static int RevertToSelf();

		public bool impersonateValidUser(String userName, String domain, String password)
		{
			WindowsIdentity tempWindowsIdentity;
			IntPtr token = IntPtr.Zero;
			IntPtr tokenDuplicate = IntPtr.Zero;
			if(LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE, 
				LOGON32_PROVIDER_DEFAULT, ref token) != 0)
			{
				if(DuplicateToken(token, 2, ref tokenDuplicate) != 0) 
				{
					tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
					impersonationContext = tempWindowsIdentity.Impersonate();
					if (impersonationContext != null)
						return true;
					else
						return false; 
				}
				else
				{
					throw new ImpersonationException(string.Format("DuplicateToken failed. ErrorCode={0}", Marshal.GetLastWin32Error()));
				}
			} 
			else
			{
				throw new ImpersonationException(string.Format("LogonUser failed. ErrorCode={0}", Marshal.GetLastWin32Error()));
			}
		}

		public void undoImpersonation()
		{
			impersonationContext.Undo();
		} 
	}
}
